package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.movechess.MoreColorCost;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.utils.Pair;

import java.util.*;

/**
 * 秋播
 */
public class AutumnSeedingRoom extends Room {


    private CacheSign chessBoardCacheSign; //背景缓存标记
    private static final String blackPlayerColor = "#BF60FF"; //黑方颜色 - 紫色
    private static final String whitePlayerColor = "#38FFA0"; //白方颜色 - 绿色
    private final int[][] stoneGrooves = new int[2][12]; //石子凹槽容器，第一行为黑方，第二行为白方
    private final int[] finalStones = new int[2]; //终点石子数量，第一个是黑方，第二个是白方

    private List<Integer> seedAnimationIndexList; //播种动画提示点
    private int remainingStones; //剩余的石子数量
    private int[] bifurcationPointGroove; //分歧点石槽 （选择击退对方还是推进己方）

    public AutumnSeedingRoom(String roomName) {
        super(roomName, "这是某猪在逆界第四届设计比赛的投稿", "秋播", GridsUtils.createEmptyGrids(4, 8), true, true);
        initChessBoardCacheSign();
    }

    //棋盘背景的设计
    private void initChessBoardCacheSign() {
        List<Sign> chessboardStyle = new ArrayList<>();
        //大黑色背景
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), ColorCost.BLACK, ColorCost.BLACK, 20f, 0, 0));
        float cuSize = 1.2f;
        float xiSize = 0.3f;
        //外边框
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), ColorCost.TRANSPARENT, ColorCost.WHITE, cuSize, 0, 0));
        //横线
        chessboardStyle.add(makeSideLine(1, 0, 1, 6, 0, 2, ColorCost.WHITE, cuSize, 0));
        chessboardStyle.add(makeSideLine(1, 6, 1, 7, 0, 2, ColorCost.WHITE_TRANSLUCENT, xiSize, 0));
        chessboardStyle.add(makeSideLine(2, 2, 2, 7, 0, 2, ColorCost.WHITE, cuSize, 0));
        chessboardStyle.add(makeSideLine(3, 0, 3, 6, 0, 2, ColorCost.WHITE, cuSize, 0));
        chessboardStyle.add(makeSideLine(3, 6, 3, 7, 0, 2, ColorCost.WHITE_TRANSLUCENT, xiSize, 0));
        //竖线
        chessboardStyle.add(makeSideLine(0, 2, 0, 2, 0, 6, ColorCost.WHITE, cuSize, 0));
        chessboardStyle.add(makeSideLine(1, 2, 2, 2, 0, 6, ColorCost.WHITE_TRANSLUCENT, xiSize, 0));
        chessboardStyle.add(makeSideLine(3, 2, 3, 2, 0, 6, ColorCost.WHITE, cuSize, 0));
        chessboardStyle.add(makeSideLine(0, 3, 3, 3, 0, 6, ColorCost.WHITE_TRANSLUCENT, xiSize, 0));
        chessboardStyle.add(makeSideLine(0, 4, 3, 4, 0, 6, ColorCost.WHITE_TRANSLUCENT, xiSize, 0));
        chessboardStyle.add(makeSideLine(0, 5, 3, 5, 0, 6, ColorCost.WHITE_TRANSLUCENT, xiSize, 0));
        chessboardStyle.add(makeSideLine(0, 6, 3, 6, 0, 6, ColorCost.WHITE_TRANSLUCENT, xiSize, 0));
        chessboardStyle.add(makeSideLine(0, 7, 3, 7, 0, 6, ColorCost.WHITE_TRANSLUCENT, xiSize, 0));
        //箭头方向标记
        chessboardStyle.add(new TitleSign(1f, 0.85f / 4, 2, " ↘", ColorCost.WHITE, 0.25f));
        chessboardStyle.add(new TitleSign(1f, 1.10f / 4, 2, " ↙", ColorCost.WHITE, 0.25f));
        chessboardStyle.add(new TitleSign(1f, 2.85f / 4, 2, " ↖", ColorCost.WHITE, 0.25f));
        chessboardStyle.add(new TitleSign(1f, 3.10f / 4, 2, " ↗", ColorCost.WHITE, 0.25f));
        //格子序号
        for (int i = 1; i <= 6; i++) {
            chessboardStyle.add(new BadgeSign(getIndex(0, 1 + i), i + "", 6, ColorCost.WHITE, ColorCost.TRANSPARENT));
            chessboardStyle.add(new BadgeSign(getIndex(1, 1 + i), (13 - i) + "", 0, ColorCost.WHITE, ColorCost.TRANSPARENT));
            chessboardStyle.add(new BadgeSign(getIndex(2, 1 + i), (13 - i) + "", 6, ColorCost.WHITE, ColorCost.TRANSPARENT));
            chessboardStyle.add(new BadgeSign(getIndex(3, 1 + i), i + "", 0, ColorCost.WHITE, ColorCost.TRANSPARENT));
        }
        //玩家标签
        chessboardStyle.add(new TitleSign(1f / 8, 0.45f / 4, 0, "黑 方", blackPlayerColor, 0.45f));
        chessboardStyle.add(new TitleSign(1f / 8, 3.45f / 4, 0, "白 方", whitePlayerColor, 0.45f));
        //添加到缓存标记
        chessBoardCacheSign = new CacheSign(this, "chessBoardCacheSign", 3, true, chessboardStyle); //*** 修改背景样式记得改这里的版本号！！！
    }

    //创建一条粗路径
    public PathSign makeSideLine(final int fRow, final int fCol, final int tRow, final int tCol, int firstPos, int secondPos, String color, float size, int style) {
        List<Pair<Integer, Integer>> nodes = new ArrayList<>();
        nodes.add(new Pair<>(getIndex(fRow, fCol), firstPos));
        nodes.add(new Pair<>(getIndex(tRow, tCol), secondPos));
        return new PathSign(nodes, color, color, size, style);
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        return chessBoardCacheSign;
    }

    @Override
    public String getRuleText() {
        return "《秋播》\n" +
                "初始布局：如上图所示，在最靠近双方的一行(1~6 号格子)中，每格放置 4 枚棋子。\n" +
                "绿先，双方轮流行动，不允许跳过。\n" +
                "格子序号从小到大为正方向，从大到小为反方向。\n" +
                "播种规则：每次行动，拿取一个非空己方格中的全部棋子，沿正方向依次向每个格子中放置 1 枚手中的棋子，这个过程称为播种。当播种到终点格时，若手中还有棋子，则沿己方格反方向播种；若播种到起点格, 则再次沿正方向播种。\n" +
                "连动规则：放置最后 1 枚棋子时——\n" +
                "   1. [击退] 若最后 1 枚棋子放在己方第 2 行(7~12 号格子)的空格，且与之编号相同的对方格非空：则拿取其中全部棋子，沿对方格 反方向播种，随后行动结束。<若条件成立则必须执行>\n" +
                "   2. [推进] 若最后 1 枚棋子放在空格，且正方向的下一个 己方 格非空，则拿取其中全部棋子正方向播种；若最后 1 枚棋子仍落到空格，则再次触发连动规则，否则行动结束。<若条件成立则必须执行>\n" +
                "   3. 若 1.与 2.的条件同时成立：则二选一执行。\n" +
                "胜负判定：播种结束时，若己方所有棋子都落入终点格，则获胜。";
    }

    @Override
    public String getCoordMode() {
        return "00000000";
    }

    @Override
    public String getGameInfo() {
        signList.clear();
        //绘制背景
        signList.add(chessBoardCacheSign);
        //绘制格子石子
        for (int i = 1; i <= 6; i++) {
            int a = stoneGrooves[0][i - 1];
            if (a != 0) {
                signList.add(new TextSign(getIndex(0, 1 + i), a + "", blackPlayerColor));
            }
            int b = stoneGrooves[0][12 - i];
            if (b != 0) {
                signList.add(new TextSign(getIndex(1, 1 + i), b + "", blackPlayerColor));
            }
            int c = stoneGrooves[1][12 - i];
            if (c != 0) {
                signList.add(new TextSign(getIndex(2, 1 + i), c + "", whitePlayerColor));
            }
            int d = stoneGrooves[1][i - 1];
            if (d != 0) {
                signList.add(new TextSign(getIndex(3, 1 + i), d + "", whitePlayerColor));
            }
        }
        //绘制终点石子
        signList.add(new TitleSign(1.0f / 8, 1.4f / 4, 0, finalStones[0] + "", blackPlayerColor, 0.65f));
        signList.add(new TitleSign(1.0f / 8, 2.4f / 4, 0, finalStones[1] + "", whitePlayerColor, 0.65f));
        //绘制播种动画的轨迹
        if (seedAnimationIndexList != null) {
            for (int i = 0; i < seedAnimationIndexList.size(); i++) {
                //画动画起点
                if (i == 0) {
                    int startIndex = seedAnimationIndexList.get(i);
                    //画初始点击框
                    signList.add(new GroundSign(startIndex, ColorCost.TRANSPARENT, "#FF00BFFF", 1.2f));
                    //画剩余可落石数
                    if (remainingStones > 0) {
                        signList.add(new BadgeSign(startIndex, "" + remainingStones, 4, "#FF00BFFF", ColorCost.TRANSPARENT));
                    }
                }
                //画变化点
                else {
                    int index = seedAnimationIndexList.get(i);
                    //画+1提示框
                    signList.add(new BadgeSign(index, "+", 2, "#FF00BFFF", ColorCost.TRANSPARENT));
                }
            }
        }
        //绘制分歧点
        if (bifurcationPointGroove != null) {
            //绘制击退点
            int[] jtIndex = new int[]{1 - bifurcationPointGroove[0], bifurcationPointGroove[1]};
            int[] jtPos = getPosByGrooveIndex(jtIndex);
            signList.add(new GroundSign(getIndex(jtPos[0], jtPos[1]), ColorCost.GRAY_TRANSLUCENT, ColorCost.TRANSPARENT, 1f));
            //绘制推进点
            int[] tjIndex = new int[]{bifurcationPointGroove[0], bifurcationPointGroove[1] + 1};
            int[] tjPos = getPosByGrooveIndex(tjIndex);
            signList.add(new GroundSign(getIndex(tjPos[0], tjPos[1]), ColorCost.GRAY_TRANSLUCENT, ColorCost.TRANSPARENT, 1f));
        }
        return super.getGameInfo();
    }

    @Override
    protected void onStartPrepare() {
        //初设棋子
        for (int i = 0; i < 6; i++) {
            stoneGrooves[0][i] = 4;
            stoneGrooves[1][i] = 4;
        }
        //绿先行动
        noticeWhiteMove();
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        for (int[] groove : stoneGrooves) {
            Arrays.fill(groove, 0);
        }
        Arrays.fill(finalStones, 0);
        seedAnimationIndexList = null;
        bifurcationPointGroove = null;
    }

    @Override
    public void doRule(int row, int col, int value) {
        //没有分歧点时，选择播种起点
        if (bifurcationPointGroove == null) {
            //根据触摸坐标获取石槽的索引
            int[] grooveIndex = getGrooveIndexByPos(row, col);
            //触摸的是己方石槽
            if (grooveIndex != null && grooveIndex[0] + 1 == value) {
                //获取石槽的石子数量
                int count = stoneGrooves[grooveIndex[0]][grooveIndex[1]];
                //只能选择有石子的石槽
                if (count > 0) {
                    stepAdd(); //增加回合数
                    stoneGrooves[grooveIndex[0]][grooveIndex[1]] = 0; //置空，表示拿起了所有石子
                    remainingStones = count; //记录剩余没有分配的石子数量
                    seedAnimationIndexList = new ArrayList<>(); //记录提示动画
                    seedAnimationIndexList.add(getIndex(row, col));
                    noticeNoMove(); //开始动画推进禁止双方点击
                    startSeed(value - 1, grooveIndex[1] + 1, 1); //开始播种
                }
            }
        }
        //有分歧点时，选择分歧点
        else {
            int[] grooveIndex = getGrooveIndexByPos(row, col);
            if (grooveIndex != null) {
                //点击的是击退点
                if (grooveIndex[0] == 1 - bifurcationPointGroove[0] && grooveIndex[1] == bifurcationPointGroove[1]) {
                    bifurcationPointGroove = null; //删除分歧点
                    int count = stoneGrooves[grooveIndex[0]][grooveIndex[1]];
                    stoneGrooves[grooveIndex[0]][grooveIndex[1]] = 0; //置空，表示拿起了所有石子
                    remainingStones = count; //记录剩余没有分配的石子数量
                    seedAnimationIndexList = new ArrayList<>(); //记录提示动画
                    seedAnimationIndexList.add(getIndex(row, col));
                    noticeNoMove(); //开始动画推进禁止双方点击
                    doRepel(grooveIndex[0], grooveIndex[1] - 1, -1); //执行击退
                }
                //点击的是推进点
                else if (grooveIndex[0] == bifurcationPointGroove[0] && grooveIndex[1] == bifurcationPointGroove[1] + 1) {
                    bifurcationPointGroove = null; //删除分歧点
                    int count = stoneGrooves[grooveIndex[0]][grooveIndex[1]];
                    stoneGrooves[grooveIndex[0]][grooveIndex[1]] = 0; //置空，表示拿起了所有石子
                    remainingStones = count; //记录剩余没有分配的石子数量
                    seedAnimationIndexList = new ArrayList<>(); //记录提示动画
                    seedAnimationIndexList.add(getIndex(row, col));
                    noticeNoMove(); //开始动画推进禁止双方点击
                    startSeed(grooveIndex[0], grooveIndex[1] + 1, 1); //执行推进
                }
            }
        }
    }

    /**
     * 递归播种动画
     *
     * @param side           石槽的阵营 0黑方，1白方
     * @param tarGrooveIndex 石槽的索引 0-11
     * @param dir            推进方向： 1正方向 or -1反方向
     */
    private void startSeed(int side, int tarGrooveIndex, int dir) {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                remainingStones--; //手上剩余石子数量减少
                //目标是终点格时
                if (tarGrooveIndex == 12) {
                    finalStones[side]++; //石子播种到终点，终点计数增加
                    seedAnimationIndexList.add(side == 0 ? getIndex(0, 1) : getIndex(2, 1));
                }
                //目标是普通格时
                else {
                    stoneGrooves[side][tarGrooveIndex]++; //石子播种到石槽，石槽计数增加
                    int[] gI = {side, tarGrooveIndex};
                    int[] pos = getPosByGrooveIndex(gI);
                    int index = getIndex(pos[0], pos[1]);
                    seedAnimationIndexList.add(index);
                }
                noticeAllRefreshGameInfo(); //通知界面刷新
                //还有没播种完的石子时
                if (remainingStones > 0) {
                    //播种到终点格时，则逆向继续播种
                    if (tarGrooveIndex == 0 || tarGrooveIndex == 12) {
                        startSeed(side, tarGrooveIndex - dir, -dir);
                    }
                    //没有播种完就递归播种
                    else {
                        startSeed(side, tarGrooveIndex + dir, dir);
                    }
                }
                //所有石子都播种完了
                else {
                    //满足击退的条件：
                    if (tarGrooveIndex >= 6 && tarGrooveIndex < 12 && stoneGrooves[side][tarGrooveIndex] == 1 && stoneGrooves[1 - side][tarGrooveIndex] > 0) {
                        //同时满足推退的条件，产生分歧点
                        if (tarGrooveIndex < 11 && stoneGrooves[side][tarGrooveIndex] == 1 && stoneGrooves[side][tarGrooveIndex + 1] > 0) {
                            //记录分歧点，并且让当前玩家继续操作，选择条件进行连锁
                            bifurcationPointGroove = new int[]{side, tarGrooveIndex};
                            if (side == 0) {
                                noticeBlackMove();
                            }
                            else {
                                noticeWhiteMove();
                            }
                        }
                        //仅满足击退条件执行击退动画
                        else {
                            int opposingSide = 1 - side;
                            int opposingIndex = tarGrooveIndex;
                            int count = stoneGrooves[opposingSide][opposingIndex];
                            stoneGrooves[opposingSide][opposingIndex] = 0; //置空，表示拿起了所有石子
                            remainingStones = count; //记录剩余没有分配的石子数量
                            seedAnimationIndexList = new ArrayList<>(); //记录提示动画
                            int[] gI = {opposingSide, opposingIndex};
                            int[] pos = getPosByGrooveIndex(gI);
                            seedAnimationIndexList.add(getIndex(pos[0], pos[1]));
                            noticeAllRefreshGameInfo();
                            doRepel(opposingSide, opposingIndex - 1, -1); //递归击退
                        }
                    }
                    //仅满足推进的条件：
                    else if (tarGrooveIndex < 11 && stoneGrooves[side][tarGrooveIndex] == 1 && stoneGrooves[side][tarGrooveIndex + 1] > 0) {
                        int advIndex = tarGrooveIndex + 1;
                        int count = stoneGrooves[side][advIndex];
                        stoneGrooves[side][advIndex] = 0; //置空，表示拿起了所有石子
                        remainingStones = count; //记录剩余没有分配的石子数量
                        seedAnimationIndexList = new ArrayList<>(); //记录提示动画
                        int[] gI = {side, advIndex};
                        int[] pos = getPosByGrooveIndex(gI);
                        seedAnimationIndexList.add(getIndex(pos[0], pos[1]));
                        noticeAllRefreshGameInfo();
                        startSeed(side, advIndex + 1, 1); //递归推进
                    }
                    //播种完了没有连锁，则切换行动方
                    else {
                        checkGameOver(2 - side);
                    }
                }
            }
        }, 250);

    }

    /**
     * 递归击退动画
     */
    private void doRepel(int side, int tarGrooveIndex, int dir) {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                remainingStones--; //手上剩余石子数量减少
                //目标是终点格时
                if (tarGrooveIndex == 12) {
                    finalStones[side]++; //石子播种到终点，终点计数增加
                    seedAnimationIndexList.add(side == 0 ? getIndex(0, 1) : getIndex(2, 1));
                }
                //目标是普通格时
                else {
                    stoneGrooves[side][tarGrooveIndex]++; //石子播种到石槽，石槽计数增加
                    int[] gI = {side, tarGrooveIndex};
                    int[] pos = getPosByGrooveIndex(gI);
                    int index = getIndex(pos[0], pos[1]);
                    seedAnimationIndexList.add(index);
                }
                noticeAllRefreshGameInfo(); //通知界面刷新
                //还有没播种完的石子时
                if (remainingStones > 0) {
                    //播种到终点格时，则逆向继续播种
                    if (tarGrooveIndex == 0 || tarGrooveIndex == 12) {
                        doRepel(side, tarGrooveIndex - dir, -dir);
                    }
                    //没有播种完就递归播种
                    else {
                        doRepel(side, tarGrooveIndex + dir, dir);
                    }
                }
                //所有石子都击退完了，判断是否结束
                else {
                    checkGameOver(side + 1); //击退的是黑方那就换黑方走，击退的是白方那就换白方走
                }
            }
        }, 250);
    }

    /**
     * 根据触摸的位置获取Grooves的索引
     */
    private int[] getGrooveIndexByPos(int row, int col) {
        int s = -1;
        int i = -1;
        if (row == 0) {
            s = row;
            i = col - 2;
        }
        else if (row == 1) {
            s = 0;
            i = 13 - col;
        }
        else if (row == 2) {
            s = 1;
            i = 13 - col;
        }
        else if (row == 3) {
            s = 1;
            i = col - 2;
        }
        if (s < 0 || i < 0 || s >= stoneGrooves.length || i >= stoneGrooves[0].length) {
            return null;
        }
        else {
            return new int[]{s, i};
        }
    }

    /**
     * 根据石槽的索引获取位置
     */
    private int[] getPosByGrooveIndex(int[] grooveIndex) {
        int row = -1;
        int col = -1;
        if (grooveIndex[0] == 0) {
            if (grooveIndex[1] / 6 == 0) {
                row = 0;
                col = grooveIndex[1] % 6 + 2;
            }
            else {
                row = 1;
                col = 7 - grooveIndex[1] % 6;
            }
        }
        else if (grooveIndex[0] == 1) {
            if (grooveIndex[1] / 6 == 0) {
                row = 3;
                col = grooveIndex[1] % 6 + 2;
            }
            else {
                row = 2;
                col = 7 - grooveIndex[1] % 6;
            }
        }
        if (row < 0 || col < 2 || row >= curGrids.length || col >= curGrids[0].length) {
            return null;
        }
        else {
            return new int[]{row, col};
        }
    }

    /**
     * 检查游戏是否结束
     * @param noOverMoveSide 如果没有结束应该移动的一方
     */
    private void checkGameOver(int noOverMoveSide){
        if (finalStones[0] == 24) {
            doOver(WinMode.BLACK_WIN, "紫色黑方胜！");
        }
        else if (finalStones[1] == 24) {
            doOver(WinMode.WHITE_WIN, "青色白方胜！");
        }
        else {
            if (noOverMoveSide == 1) {
                noticeBlackMove();
            }
            else {
                noticeWhiteMove();
            }
        }
    }
}
